Github에서 예제 코드를 확인할 수 있어요.
기존 보고서를 보자
종목 | 주 | 가격 | 합계 |
IBM | 1000 | 25 | 25000 |
GE | 400 | 100 | 40000 |
ㅤ | ㅤ | 합계 | 65000 |
새로운 보고서는 다중 통화를 지원하는 보고서를 만드려면 통화 단위를 추가해야 한다.
종목 | 주 | 가격 | 합계 |
IBM | 1000 | 25USD | 25000USD |
Novartis | 400 | 150CHF | 60000CHF |
ㅤ | ㅤ | 합계 | 65000USD |
환율도 명시해야 한다.
기준 | 변환 | 환율 |
CHF | USD | 1.5 |
TODO LIST
$5 + 10CHF = $10(환율이 2:1)일 경우
$5 X 2 = $10
새로운 보고서를 생성하려면 어떤 기능들이 있어야 할까? 즉, 어떤 테스트가 있어야(모두 통과할 경우) 보고서가 완성됐다는 것을 확신할 수 있을까?
- 통화가 다른 두 금액을 더해서 주어진 환율에 맞게 변한 금액을 결과로 얻을 수 있어야 한다.
- 어떤 금액(주가)을 어떤 수(주식의 수)에 곱한 금액을 결과로 얻을 수 있어야 한다.
우선 어떤 테스트가 필요할까? 할 일 목록을 보니 첫번째 보다는 두번째가 더 간단해 보인다. 테스트를 작성할 땐 완벽한 인터페이스에 대해 상상해보는 것이 좋다. 우리는 지금 외부에서 어떤 식으로 보일지에 대한 테스트 코드를 적는 것이다.
테스트 구성하기
from django.test import TestCase class TestDollar(TestCase): def setUp(self): pass def TearDown(self): pass def test_multiplication(self): five = Dollar(5) five.times(2) self.assertEqual(10, five.amount)
>>> python moneyapp/manage.py test moneys Creating test database for alias 'default'... System check identified no issues (0 silenced). E ====================================================================== ERROR: test_multiplication (moneys.tests.TestDollar) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/googie/Desktop/TDD-example/moneyapp/moneys/tests.py", line 12, in test_multiplication five = Dollar(5) NameError: name 'Dollar' is not defined ---------------------------------------------------------------------- Ran 1 test in 0.000s FAILED (errors=1) Destroying test database for alias 'default'...
- Dollar 클래스 없음
- 생성자가 없음
- times() 메서드가 없음
- amount 필드가 없음
하나씩 TODO를 지워가보자. Dollar 클래스를 정의하면 하나를 없앨 수 있다.
class Dollar: def __init__(self, amount: int): self.amount = amount def times(self, multiplier: int): pass
>>> python moneyapp/manage.py test moneys Creating test database for alias 'default'... System check identified no issues (0 silenced). F ====================================================================== FAIL: test_multiplication (moneys.tests.TestDollar) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/googie/Desktop/TDD-example/moneyapp/moneys/tests.py", line 15, in test_multiplication self.assertEqual(10, five.amount) AssertionError: 10 != 5 ---------------------------------------------------------------------- Ran 1 test in 0.000s FAILED (failures=1) Destroying test database for alias 'default'...
테스트를 성공시켜 보자.
class Dollar: def __init__(self, amount: int): self.amount = 10
>>> python moneyapp/manage.py test moneys Creating test database for alias 'default'... System check identified no issues (0 silenced). . ---------------------------------------------------------------------- Ran 1 test in 0.000s OK Destroying test database for alias 'default'...
이제 상수가 아닌 변수로 변경해서 점진적으로 일반화를 시켜보자.
class Dollar: def __init__(self, amount: int): self.amount = amount def times(self, multiplier: int): self.amount *= multiplier
테스트의 주기
- 작은 테스트를 하나 추가한다.
- 모든 테스트를 실행해서 테스트가 실패하는 것을 확인한다.
- 조금 수정한다.
- 모든 테스트를 실행해서 테스트가 성공하는 것을 확인한다.
- 중복을 제거하기 위해 리팩터링을 한다.
TODO LIST
$5 + 10CHF = $10(환율이 2:1)일 경우
$5 X 2 = $10
amount를 private 만들기
Dollar 부작용
Money 반올림
이제 첫번째 테스트에 완료를 표시할 수 있게 됐다. 우리는 다음 작업을 해냈다.
- 우리가 알고 있는 작업해야 할 테스트 목록을 만들었다.
- 오퍼레이션이 외부에서 어떻게 보이길 원하는지 말해주는 이야기를 코드로 표현했다.
- 스텁(테스트에 필요한 호출에 대해 미리 준비된 답을 제공하는 객체) 구현을 통해 테스트를 실행했다.
- 끔찍한 방법으로라도 테스트를 통과시켰다.
- 상수를 변수로 변경하여 점진적으로 일반화했다.
댓글